<?php

class wgHelper {
	public static $dateFormatter = null;
	public static $cmpMethod = null;
	public static $invertComparison = false;

	public static function checkRequired($options, $required) {
		if (!is_array($options)) {
			throw new InvalidArgumentException('You must pass an array of options to execute helper method');
		}
		if (is_string($required)) {
			$required = array($required);
		}
		foreach ($required as $key) {
			if (!is_array($key)) { // OR
				$key = array($key);
			}
			$conditionOr = false;
			foreach ($key as $orKey) {
				if (!is_array($orKey)) { // OR
					$orKey = array($orKey);
				}
				$conditionAnd = true;
				foreach ($orKey as $andKey) {
					$conditionAnd &= isset($options[$andKey]);
				}
				$conditionOr |= $conditionAnd;
			}
			if (!$conditionOr) {
				throw new InvalidArgumentException('You must pass "'.$key.'" option to execute helper method');
			}
		}
		return $options;
	}

	public static function applyIf($options, $defaults) { // ExtJS-style naming
		// Using this method implies that $options variable is array and contains all required keys
		foreach ($defaults as $key=>$value) {
			if (!isset($options[$key])) {
				$options[$key] = $defaults[$key];
			}
		}
		return $options;
	}

	public static function getOptions($options, $required, $defaults) {
		self::checkRequired($options, $required);
		return self::applyIf($options, $defaults);
	}

	public static function normalizePath($v) {
		$v = str_replace(sfConfig::get('sf_web_dir'),'',$v);
		$v = str_replace(DIRECTORY_SEPARATOR, '/', $v);
		return $v;
	}

	public static function cmp($a, $b) {
		return (self::$invertComparison? -1 : 1)*(call_user_func(array($a, self::$cmpMethod)) - call_user_func(array($b, self::$cmpMethod)));
	}

	public static function cmpRating($a, $b) {
		$aVotesInfo = $a['object']->getVotesInfo();
		$bVotesInfo = $b['object']->getVotesInfo();
		return $aVotesInfo['sum'] < $bVotesInfo['sum']? -1 : 1;
	}

	public static function isEmpty($value) {
		if (is_array($value)) {
			$empty = true;
			foreach ($value as $key=>$value) {
				$empty &= self::isEmpty($value);
			}
			return $empty;
		}
		if (empty($value)) return true;
	}

	public static function peerify($presets, $requests = array()) {
		$results = array();
		if (!is_array($presets)) $presets = array('model' => is_object($presets)? $results[] = get_class($presets) : $presets);
		foreach ($presets as $name => $value) {
			if (($pos = stripos($name, 'model')) !== false) {
				$peerName = str_ireplace('model', '', $name).'Peer';
				$results[] = $presets[mb_lcfirst($peerName)] = $value.'Peer';
			}
		}
		foreach ($requests as $name => $instruction) {
			$value = '';
			foreach ($instruction as $term) {
				$value .= isset($presets[$term])? $presets[$term] : $term;
			}
			$results[] = $presets[$name] = $value;
			$results[] = $presets[$name.'Peer'] = $value.'Peer';
		}
		return $results;
	}

	public static function getModelName() {
		return sfInflector::camelize(sfContext::getInstance()->getModuleName());
	}

	public static function incrementRe($str) {
		if (($repos = mb_stripos($str, 'Re:')) !== false) {
			$str = mb_str_replace('Re:', 'Re(2):', $str);
		} else if (($repos = mb_stripos($str, 'Re(')) !== false) {
			$closingBracket = mb_stripos($str, ')', $repos);
			$search = mb_substr($str, $repos, $closingBracket-$repos+2);
			$num = (int)mb_substr($str, $repos+3, $closingBracket);
			$num++;
			$str = mb_str_replace($search, 'Re('.$num.'):', $str);
		} else {
			$str = 'Re: '.$str;
		}
		return $str;
	}
	
	public static function choose() {
		$args = func_get_args();
		foreach ($args as $arg) {
			if ($arg) return $arg;
		}
		return $arg;
	}
	
	public static function pa($value = 'hello', $options = array()) {
		if (!sfConfig::get('sf_logging_enabled')) return;
		static $index = -1;
		$index++;

		if (is_bool($options)) { // Shortcuts
			$options = array('echo' => $options);
		} else if (is_string($options)) {
			$options = array('header' => $options);
		}
		$required = array();
		$defaults = array(
      'echo' => false,
      'fire' => true,
      'header' => ''
      );
      $options = wgHelper::getOptions($options, $required, $defaults);

      if (is_array($value) || is_object($value)) {
      	$displayValue = print_r($value,true);
      } else if (is_bool($value)) {
      	$displayValue = $value? 'true' : 'false';
      } else {
      	$displayValue = $value;
      }

      $class = '';
      $backtrace = debug_backtrace();
      if (isset($backtrace[1])) {
      	if (isset($backtrace[1]['class'])) {
        $class = $backtrace[1]['class'];
      	} else {
        if (isset($backtrace[2]['class'])) {
        	$class = $backtrace[2]['class']; // Either called statically or through an alias function (the latter way adds an element to the backtrace)
        } else {
        	$class = $backtrace[2]['file']; // Called from template
        }
      	}
      }

      $info = '{'.$class.'} Debug '.$index.' '.$options['header'].': '.$displayValue;
      try {
      	sfContext::getInstance()->getLogger()->info($info);
      } catch (sfException $e) {
      	// If pa() is called in save() method of a model class, it will produce an error 'The "default" context doesn\'t exist'
      }
      if ($options['fire']) {
      	$firephp = sfFirePHP::getInstance(true);
      	$firephp->fb($value, $options['header']);
      }
      if ($options['echo']) {
      	echo $info;
      }
      return $info;
	}
}
